package watchtcp

import (
	"bufio"
	globaldata "earth/global_data"
	httpclient "earth/http_client"
	psi "earth/watch_tcp/platform_send_instruction"
	tsi "earth/watch_tcp/terminal_send_instruction"
	watchmessgae "earth/watch_tcp/watch_message"
	"net"
	"sync"

	MQTT "earth/mqtt"

	"github.com/sirupsen/logrus"
	"github.com/spf13/viper"
)

type WatchTcp struct {
	Mutex        *sync.Mutex
	Conn         net.Conn
	DeviceID     string
	TsiFunction  *tsi.TsiFunction
	PsiFunction  *psi.PsiFunction
	Manufacturer string
	IMEI         string
	ReplyFlag    bool
}

// 当设备与平台连接的时候，开启一个goroutine接管连接
func NewWatchTcp(conn net.Conn) {

	w := &WatchTcp{
		Conn:  conn,
		Mutex: &sync.Mutex{},
	}
	w.Start()
}

func (w *WatchTcp) Start() {
	// 鉴权
	err := w.auth()
	if err != nil {
		logrus.Println("auth failed")
		w.Close()
		return
	}
	// 循环读取设备发送的数据
	var tsiFunction tsi.TsiFunction
	tsiFunction.Init()
	var psiFunction psi.PsiFunction
	psiFunction.Init()
	w.TsiFunction = &tsiFunction
	w.PsiFunction = &psiFunction
	w.read()

}

// 断开连接,多次关闭无所谓
func (w *WatchTcp) Close() {
	logrus.Println("Close")
	err := w.Conn.Close()
	if err != nil {
		logrus.Error("Error closing:", err.Error())
	} else {
		if w.DeviceID != "" {
			// 发送设备下线状态
			m := *MQTT.MqttClient
			viper.SetDefault("version", "new")
			if viper.GetString("version") == "new" {
				err = m.SendStatus(w.DeviceID, "0")
			} else {
				err = m.SendStatus(w.IMEI, "0")
			}
			if err != nil {
				logrus.Info("SendStatus() failed, err: ", err)
			}
			logrus.Info("设备下线：", w.DeviceID)

		}
	}
}

// 首次消息鉴权
func (w *WatchTcp) auth() error {
	// 读取设备发送的数据
	message, err := bufio.NewReader(w.Conn).ReadString('\n')
	if err != nil {
		logrus.Error("Error reading:", err.Error())
		return err
	}
	// 去掉换行符
	message = message[:len(message)-1]
	logrus.Debug("\ndevice====>i:", string(message))
	watchMessage, err := watchmessgae.ParseMessage(message)
	if err != nil {
		logrus.Error("ParseMessage failed:", err.Error())
		return err
	}
	w.IMEI = watchMessage.IMEI
	w.Manufacturer = watchMessage.Manufacturer
	// 根据watchMessage.IMEI获取设备信息
	var voucher string
	if viper.GetString("version") == "new" {
		voucher = `{"imei":"` + watchMessage.IMEI + `"}`
	} else {
		voucher = watchMessage.IMEI
	}
	// 读取设备配置
	tpDeviceConfig, err := httpclient.GetDeviceConfig(voucher, "")
	if err != nil {
		// 获取设备配置失败，请检查连接包是否正确
		logrus.Error(err)
		return err
	}
	logrus.Info("获取设备配置成功：", tpDeviceConfig)
	// 发送设备上线状态
	m := *MQTT.MqttClient
	if viper.GetString("version") == "new" {
		err = m.SendStatus(tpDeviceConfig.Data.ID, "1")
	} else {
		err = m.SendStatus(watchMessage.IMEI, "1")
	}
	if err != nil {
		logrus.Info("SendStatus() failed, err: ", err)
	}
	logrus.Info("设备上线：", tpDeviceConfig.Data.ID)
	//存入全局变量
	globaldata.DeviceConfigMap.Store(tpDeviceConfig.Data.ID, &tpDeviceConfig.Data)
	globaldata.DeviceConnectionMap.Store(tpDeviceConfig.Data.ID, w)
	globaldata.IMEIToDeviceIDMap[watchMessage.IMEI] = tpDeviceConfig.Data.ID
	w.DeviceID = tpDeviceConfig.Data.ID
	go w.ParseAndDeal(message)
	return nil
}

// 循环读取设备发送的数据
func (w *WatchTcp) read() {
	for {
		message, err := bufio.NewReader(w.Conn).ReadString('\n')
		if err != nil {
			logrus.Error("Error reading:", err.Error())
			w.Close()
			return
		}
		// 去掉换行符
		message = message[:len(message)-1]
		logrus.Debug("\ndevice====>i:", message)
		// 开启一个goroutine处理设备发送的数据
		go w.ParseAndDeal(message)

	}
}

// 回复消息
func (w *WatchTcp) reply(watchMessage *watchmessgae.WatchMessage) {
	message := watchmessgae.ReplyMessage(watchMessage)
	w.Mutex.Lock()
	defer w.Mutex.Unlock()
	_, err := w.Conn.Write([]byte(message))
	if err != nil {
		logrus.Error("Error writing:", err.Error())
		w.Close()
	}
	logrus.Debug("\ni====>device:", message)
}

func (w *WatchTcp) ParseAndDeal(message string) {
	watchMessage, err := watchmessgae.ParseMessage(message)
	if err != nil {
		logrus.Error("ParseMessage failed")
		return
	}
	logrus.Println("MessageID:KA")

	// 从映射表中取出对应的处理函数
	if dealFunc, ok := w.TsiFunction.DealFuncs[watchMessage.MessageID]; ok {
		err = dealFunc(watchMessage, w.DeviceID)
	} else {
		logrus.Error("Other message:" + watchMessage.MessageID)
		return
	}

	// 处理失败
	if err != nil {
		logrus.Error("DealKA failed:", err.Error())
	} else {
		// 不需要回复的消息
		if watchMessage.MessageID != "UD" {
			w.reply(watchMessage)
		}
	}
}
